# 最新的oss接口
from dotenv import load_dotenv
import os
import alibabacloud_oss_v2 as oss

class Ossutil:
    def __init__(self, region,  bucket, endpoint=None):
        """验证权限"""
        self.cfg = oss.config.load_default()
        self.cfg.region = region
        if endpoint is not None:
            self.cfg.endpoint = endpoint
        # 从环境变量中加载凭证信息，用于身份验证
        self.credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

        self.client = oss.Client(self.cfg)
        self.bucket = bucket

    # 从文件上传到oss
    def uplaod_from_file(self, file_path, key):
        result = self.client.put_object_from_file(
            oss.PutObjectRequest(
                bucket=self.bucket,  # 存储空间名称
                key=key  # 对象名称
            ),
            file_path  # 本地文件路径
        )

        # 输出请求的结果信息，包括状态码、请求ID、内容MD5、ETag、CRC64校验码、版本ID和服务器响应时间
        print(f'status code: {result.status_code},'
              f' request id: {result.request_id},'
              f' content md5: {result.content_md5},'
              f' etag: {result.etag},'
              f' hash crc64: {result.hash_crc64},'
              f' version id: {result.version_id},'
              f' server time: {result.headers.get("x-oss-server-time")},'
              )

    # 从response.content返回的网络流上传到oss
    def upload_from_response(self, content, key):
        # 执行上传对象的请求，指定存储空间名称、对象名称和数据内容
        result = self.client.put_object(oss.PutObjectRequest(
            bucket=self.bucket,
            key=key,
            body=content,
        ))

        # 输出请求的结果状态码、请求ID、内容MD5、ETag、CRC64校验码和版本ID，用于检查请求是否成功
        print(f'status code: {result.status_code},'
              f' request id: {result.request_id},'
              f' content md5: {result.content_md5},'
              f' etag: {result.etag},'
              f' hash crc64: {result.hash_crc64},'
              f' version id: {result.version_id},'
              )

    # 分片上传针对大文件
    def uplaod_big_file(self, file_path, key):
        # 初始化分片上传请求，获取upload_id用于后续分片上传
        result = self.client.initiate_multipart_upload(oss.InitiateMultipartUploadRequest(
            bucket=self.bucket,
            key=key,
        ))

        # 定义每个分片的大小为50MB
        part_size = 50 * 1024 * 1024

        # 获取要上传文件的总大小
        data_size = os.path.getsize(file_path)

        # 初始化分片编号，从1开始
        part_number = 1

        # 存储每个分片上传的结果
        upload_parts = []

        # 打开文件以二进制模式读取
        with open(file_path, 'rb') as f:
            # 遍历文件，按照part_size分片上传
            for start in range(0, data_size, part_size):
                n = part_size
                if start + n > data_size:  # 处理最后一个分片可能小于part_size的情况
                    n = data_size - start

                # 创建SectionReader来读取文件的特定部分
                reader = oss.io_utils.SectionReader(oss.io_utils.ReadAtReader(f), start, n)

                # 上传分片
                up_result = self.client.upload_part(oss.UploadPartRequest(
                    bucket=self.bucket,
                    key=key,
                    upload_id=result.upload_id,
                    part_number=part_number,
                    body=reader
                ))

                # 打印每个分片上传的结果信息
                print(f'status code: {up_result.status_code},'
                      f' request id: {up_result.request_id},'
                      f' part number: {part_number},'
                      f' content md5: {up_result.content_md5},'
                      f' etag: {up_result.etag},'
                      f' hash crc64: {up_result.hash_crc64},'
                      )

                # 将分片上传结果保存到列表中
                upload_parts.append(oss.UploadPart(part_number=part_number, etag=up_result.etag))

                # 增加分片编号
                part_number += 1

        # 对上传的分片按照分片编号排序
        parts = sorted(upload_parts, key=lambda p: p.part_number)

        # 发送完成分片上传请求，合并所有分片为一个完整的对象
        result = self.client.complete_multipart_upload(oss.CompleteMultipartUploadRequest(
            bucket=self.bucket,
            key=key,
            upload_id=result.upload_id,
            complete_multipart_upload=oss.CompleteMultipartUpload(
                parts=parts
            )
        ))


        # 输出完成分片上传的结果信息
        print(f'status code: {result.status_code},'
              f' request id: {result.request_id},'
              f' bucket: {result.bucket},'
              f' key: {result.key},'
              f' location: {result.location},'
              f' etag: {result.etag},'
              f' encoding type: {result.encoding_type},'
              f' hash crc64: {result.hash_crc64},'
              f' version id: {result.version_id},'
              )


# if __name__ == '__main__':
#     # 加载 .env 文件中的变量（默认在当前目录查找）
#     load_dotenv()
#
#     region = os.getenv("BUCKET", "default_value_if_missing")  # 第二个参数是可选默认值
#     bucket = os.getenv("BUCKET", "default_value_if_missing")
#     endpoint = os.getenv("ENDPOINT", "default_value_if_missing")
#     o = Ossutil(region, bucket, endpoint)
#